<?php

namespace App\Libs\Cache;
use Phalcon\Cache\Frontend\Data as FrontData;
use Phalcon\Cache\Backend\Memcache as BackMemCached;

class Memcached extends \App\Libs\Base\Singleton {
    private $onoff = TRUE;
    public $config = NULL;

    /**
     * Connection pools.
     *
     * @var array
     */
    private $pools = array();
    protected function __construct() {
        is_null($this->config) && $this->config = \App\Libs\Base\Config::instance()->memcached;
        if (empty($this->config['unixsock'])) {
            $this->onoff = FALSE;
            return;
        }
        $unixnum = count($this->config['unixsock']);
        $num = rand(0, $unixnum - 1);
        $weight = 10;

        // Cache data for one hour
        $frontCache = new FrontData(array(
            "lifetime" => 3600
        ));

        // Create the component that will cache "Data" to a "Memcached" backend
        // Memcached connection settings
        $this->pools = new BackMemCached($frontCache, array(
            "servers" => array(
                array(
                    "host"   => $this->config['unixsock'][$num]['host'],
                    "port"   => $this->config['unixsock'][$num]['port'],
                    "weight" =>  $weight
                )
            )
        ));

        
        return TRUE;

    }

    public function __call($method, $arguments) {
        if ( ! $this->onoff) {
            return NULL;
        }
        return $this->$method($arguments);
    }

    /**
     * Delete an item.
     *
     * @param string $key The key to be deleted.
     * @param int $time The amount of time the server will wait to delete
     * the item.
     *
     * @return Returns TRUE on success or FALSE on failure.
     */
    protected function delete($args) {
        $key = $args[0];
        if (!isset($args[1])) {
            $args[1] = 0;
        }
        $time = $args[1];
        $result = TRUE;
        $result = $result && $this->pools->delete($key, $time);
        return $result;
    }

    /**
     * Store an item.
     *
     * @param string $key The key under which to store the value.
     * @param mixed $value The value to store.
     * @param int $expiration The expiration time, defaults to 0.
     *
     * @return Returns TRUE on success or FALSE on failure.
     */
    protected function set($args) {
        $key = $args[0];
        $value = $args[1];
        if ( ! isset($args[2])) {
            $args[2] = 300;
        }
        $expiration = $args[2];
        $result = TRUE;
        $result = $result && $this->pools->save($key, $value, $expiration);
        return $result;
    }

    /**
     * Retrieve an item.
     *
     * @param string $key The key of the item to retrieve.
     *
     * @return Returns the value stored in the cache or FALSE otherwise.
     */
    protected function get($args) {
        $key = $args[0];
        $result = FALSE;
        $result = $this->pools->get($key);

        return $result;
    }

    /**
     * Increment numeric item's value.
     */
    protected function increment($args) {
        $key = $args[0];
        if (!isset($args[1])) {
            $args[1] = 1;
        }
        $offset = $args[1];
        $result = FALSE;
        $result = $this->pools->increment($key, $offset);
        return $result;
    }

    /**
     * Decrement numeric item's value.
     */
    protected function decrement($args) {
        $key = $args[0];
        if (!isset($args[1])) {
            $args[1] = 1;
        }
        $offset = $args[1];
        $result = FALSE;
        $result = $this->pools->decrement($key, $offset);
        return $result;
    }

    /**
     * Retrieve multiple items.
     */
    protected function getMulti($args) {
        $keys = $args[0];
        if (empty($keys) || !is_array($keys)) {
            return FALSE;
        }
        return $this->pools->getMulti($keys);
    }

    /**
     * 返回最后一次操作的结果代码
     */
    public function getResultCode() {
        return $this->pools->getResultCode();
    }

    public static function __callStatic($method, $args) {
        if ( ! self::instance()->onoff) {
            return NULL;
        }
        return call_user_func_array(array(self::instance(), $method), array($args));
    }
}
